﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MostRecentlyUsed;
using Moq;
using MostRecentlyUsed.Models.EventArguments;
using System.Linq;

namespace MostRecentlyUsedTests
{
    /// <summary>
    /// Summary description for DatabaseConnectionsTests
    /// </summary>
    [TestClass]
    public class DatabaseConnectionsTests
    {
        public DatabaseConnectionsTests()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        public void GetEncryptedConnectionStrings()
        {
            var databaseConnection = new Mock<DatabaseConnections>();
            databaseConnection.CallBase = true;
            databaseConnection.Setup(d => d.Contains(It.IsAny<string>())).Returns(false);

            databaseConnection.Object.AddItem("User Id=Andy;Password=MyWord;Another=Yes", "System.Data");
            databaseConnection.Object.AddItem("User Id=Andy2;Password=MyWord2;Another=Yes", "System.Data");
            databaseConnection.Object.AddItem("User Id=Andy3;Password=MyWord3;Another=Yes", "System.Data");

            var encrypted = databaseConnection.Object.GetEncryptedConnectionStrings();

            Assert.AreEqual("ZRu9nBwpeCTtQHVwxreB6aJ57RMuneZQrIDkUCf8V7xTdpmIu9Lpode0QtvJfeXOGNYHyuY6ASRn2yK10rHM2EvjG5F8uFNv757M55l4cth8g1xPq+jI7DmCtWEV4pDYAjVnpLcUKA+OB+gZV+R2kVDxBHlvXBQ9U6kD/UTJ54lUmyz1In0fzCo8g579jMNZQwI697qFQg4YOkXQkiG+WnzLaweAcxds2q+FwMtXebaBoYUaTJIXs4rVllzwzOPTifM4Zhxo1iCvRr1wx8CtuLhbGiSG3VOQbEDU9HTzG9fFXTUSFtz1qBD1F54t07ZVYjPgx0EeIUNMC4GImeL5dEy6byyOrGg4PIdnmL5s3Yfz44+l0OYqaua7ooc43RMgO8QVGEiC2OM9/pHXVjXG3EldzqFzUCgwXGLdyLXWDqEcKOd7CAd1cyGBq7u0sUF/7eVfVLrMHRlwVHwHYDSn8GEfzyC/+RO31eyNHWNGdVLUpOTIuYSLm9sdy9omc8hVKLNyDmhdK6FtKr2yhjbsdQ39HIiLJdGd6sttcVgOhMrWvMcjHWZnH0cSYg9nvZTB", encrypted);
        }

        [TestMethod]
        public void SetEncryptedConnectionStrings()
        {
            var encryptedStrings = "ZRu9nBwpeCTtQHVwxreB6aJ57RMuneZQrIDkUCf8V7xTdpmIu9Lpode0QtvJfeXOGNYHyuY6ASRn2yK10rHM2EvjG5F8uFNv757M55l4cth8g1xPq+jI7DmCtWEV4pDYAjVnpLcUKA+OB+gZV+R2kVDxBHlvXBQ9U6kD/UTJ54lUmyz1In0fzCo8g579jMNZQwI697qFQg4YOkXQkiG+WnzLaweAcxds2q+FwMtXebaBoYUaTJIXs4rVllzwzOPTifM4Zhxo1iCvRr1wx8CtuLhbGiSG3VOQbEDU9HTzG9fFXTUSFtz1qBD1F54t07ZVYjPgx0EeIUNMC4GImeL5dEy6byyOrGg4PIdnmL5s3Yfz44+l0OYqaua7ooc43RMgO8QVGEiC2OM9/pHXVjXG3EldzqFzUCgwXGLdyLXWDqEcKOd7CAd1cyGBq7u0sUF/7eVfVLrMHRlwVHwHYDSn8GEfzyC/+RO31eyNHWNGdVLUpOTIuYSLm9sdy9omc8hVKLNyDmhdK6FtKr2yhjbsdQ39HIiLJdGd6sttcVgOhMrWvMcjHWZnH0cSYg9nvZTB";

            var databaseConnection = new Mock<DatabaseConnections>();
            databaseConnection.CallBase = true;
            databaseConnection.Setup(d => d.Contains(It.IsAny<string>())).Returns(false);

            databaseConnection.Object.SetEncryptedConnectionStrings(encryptedStrings);

            Assert.AreEqual(3, databaseConnection.Object.ConnectionStrings.Count);

            Assert.AreEqual("User Id=Andy;Another=Yes", databaseConnection.Object.ConnectionStrings[0].DisplayName);
            Assert.AreEqual("System.Data", databaseConnection.Object.ConnectionStrings[0].Provider);
            Assert.AreEqual("User Id=Andy;Password=MyWord;Another=Yes", databaseConnection.Object.ConnectionStrings[0].ConnectionString);
            Assert.AreEqual(2, databaseConnection.Object.ConnectionStrings[0].Order);

            Assert.AreEqual("User Id=Andy2;Another=Yes", databaseConnection.Object.ConnectionStrings[1].DisplayName);
            Assert.AreEqual("System.Data", databaseConnection.Object.ConnectionStrings[1].Provider);
            Assert.AreEqual("User Id=Andy2;Password=MyWord2;Another=Yes", databaseConnection.Object.ConnectionStrings[1].ConnectionString);
            Assert.AreEqual(1, databaseConnection.Object.ConnectionStrings[1].Order);

            Assert.AreEqual("User Id=Andy3;Another=Yes", databaseConnection.Object.ConnectionStrings[2].DisplayName);
            Assert.AreEqual("System.Data", databaseConnection.Object.ConnectionStrings[2].Provider);
            Assert.AreEqual("User Id=Andy3;Password=MyWord3;Another=Yes", databaseConnection.Object.ConnectionStrings[2].ConnectionString);
            Assert.AreEqual(0, databaseConnection.Object.ConnectionStrings[2].Order);
        }

        [TestMethod]
        public void AddItemNew()
        {
            var databaseConnection = new Mock<DatabaseConnections>();
            databaseConnection.CallBase = true;
            databaseConnection.Setup(d => d.Contains(It.IsAny<string>())).Returns(false);

            databaseConnection.Object.AddItem("User Id=Andy;Password=MyWord;Another=Yes", "System.Data");

            Assert.AreEqual(1, databaseConnection.Object.ConnectionStrings.Count);
            Assert.AreEqual("User Id=Andy;Another=Yes", databaseConnection.Object.ConnectionStrings[0].DisplayName);
            Assert.AreEqual("System.Data", databaseConnection.Object.ConnectionStrings[0].Provider);
            Assert.AreEqual("User Id=Andy;Password=MyWord;Another=Yes", databaseConnection.Object.ConnectionStrings[0].ConnectionString);
            Assert.AreEqual(0, databaseConnection.Object.ConnectionStrings[0].Order);
        }

        [TestMethod]
        public void AddItemExisting()
        {
            var databaseConnection = new Mock<DatabaseConnections>();
            databaseConnection.CallBase = true;
            databaseConnection.Setup(d => d.Contains(It.IsAny<string>())).Returns(true);
            databaseConnection.Setup(d => d.RemoveItemByDisplayName(It.IsAny<string>())).Verifiable();

            databaseConnection.Object.AddItem("User Id=Andy;Password=MyWord;Another=Yes", "System.Data");

            databaseConnection.VerifyAll();
            Assert.AreEqual(1, databaseConnection.Object.ConnectionStrings.Count);
            Assert.AreEqual("User Id=Andy;Another=Yes", databaseConnection.Object.ConnectionStrings[0].DisplayName);
            Assert.AreEqual("System.Data", databaseConnection.Object.ConnectionStrings[0].Provider);
            Assert.AreEqual("User Id=Andy;Password=MyWord;Another=Yes", databaseConnection.Object.ConnectionStrings[0].ConnectionString);
            Assert.AreEqual(0, databaseConnection.Object.ConnectionStrings[0].Order);
        }

        [TestMethod]
        public void AddItemVerifyOrder()
        {
            var databaseConnection = new Mock<DatabaseConnections>();
            databaseConnection.CallBase = true;
            databaseConnection.Setup(d => d.Contains(It.IsAny<string>())).Returns(false);

            databaseConnection.Object.AddItem("User Id=Andy;Password=MyWord;Another=Yes", "System.Data");
            databaseConnection.Object.AddItem("User Id=Andy2;Password=MyWord2;Another=Yes", "System.Data");
            databaseConnection.Object.AddItem("User Id=Andy3;Password=MyWord3;Another=Yes", "System.Data");

            Assert.AreEqual(2, databaseConnection.Object.ConnectionStrings[0].Order);
            Assert.AreEqual(1, databaseConnection.Object.ConnectionStrings[1].Order);
            Assert.AreEqual(0, databaseConnection.Object.ConnectionStrings[2].Order);
        }

        [TestMethod]
        public void Contains()
        {
            var databaseConnection = new Mock<DatabaseConnections>();
            databaseConnection.CallBase = true;
            databaseConnection.Setup(d => d.Contains(It.IsAny<string>())).Returns(false);

            databaseConnection.Object.AddItem("User Id=Andy;Password=MyWord;Another=Yes", "System.Data");
            databaseConnection.Object.AddItem("User Id=Andy2;Password=MyWord2;Another=Yes", "System.Data");
            databaseConnection.Object.AddItem("User Id=Andy3;Password=MyWord3;Another=Yes", "System.Data");

            databaseConnection.Reset();

            Assert.IsFalse(databaseConnection.Object.Contains("Whoopiedo"));
            Assert.IsTrue(databaseConnection.Object.Contains("User Id=Andy3;Password=MyWord3;Another=Yes"));
        }

        [TestMethod]
        public void RemoveItemByDisplayName()
        {
            var databaseConnection = new Mock<DatabaseConnections>();
            databaseConnection.CallBase = true;
            databaseConnection.Setup(d => d.Contains(It.IsAny<string>())).Returns(false);

            databaseConnection.Object.AddItem("User Id=Andy;Password=MyWord;Another=Yes", "System.Data");
            databaseConnection.Object.AddItem("User Id=Andy2;Password=MyWord2;Another=Yes", "System.Data");
            databaseConnection.Object.AddItem("User Id=Andy3;Password=MyWord3;Another=Yes", "System.Data");

            databaseConnection.Object.RemoveItemByDisplayName("User Id=Andy2;Another=Yes");

            Assert.AreEqual(2, databaseConnection.Object.ConnectionStrings.Count);
            Assert.AreEqual("User Id=Andy;Another=Yes", databaseConnection.Object.ConnectionStrings[0].DisplayName);
            Assert.AreEqual("User Id=Andy3;Another=Yes", databaseConnection.Object.ConnectionStrings[1].DisplayName);
        }

        [TestMethod]
        public void OnNewItemClick()
        {
            // Arrange
            var databaseConnection = new Mock<DatabaseConnections>();
            databaseConnection.CallBase = true;

            databaseConnection.Object.AddItem("User Id=Andy;Password=MyWord;Another=Yes", "System.Data");
            databaseConnection.Object.AddItem("User Id=Andy2;Password=MyWord2;Another=Yes", "System.Data");
            databaseConnection.Object.AddItem("User Id=Andy3;Password=MyWord3;Another=Yes", "System.Data");

            bool isCalled = false;
            databaseConnection.Object.ItemSelectedEvent += (sender, e) => isCalled = true;

            var connectionString = new SelectedConnectionString(
                    "User Id=Andy2;Password=MyWord2;Another=Yes",
                    "System.Data",
                    databaseConnection.Object.ItemsToReplace
                    );
            var item = new ConnectionStringMenuItem(connectionString);

            // Act
            databaseConnection.Object.OnNewItemClick(item, new EventArgs());

            // Assert
            Assert.IsTrue(isCalled);
            Assert.AreEqual(3, databaseConnection.Object.ConnectionStrings.Count);
            Assert.AreEqual(connectionString, databaseConnection.Object.ConnectionStrings.Single(a => a.Order == 0));
        }
    }
}
